package service

import (
	"database/sql"
	"fmt"
	lm "github.com/PhlexTheCharr/gofurry-cloud-service/apps/openlist/manage/log/models"
	oum "github.com/PhlexTheCharr/gofurry-cloud-service/apps/openlist/util/models"
	"github.com/PhlexTheCharr/gofurry-cloud-service/common/abstract"
	"github.com/PhlexTheCharr/gofurry-cloud-service/common/log"
	"github.com/PhlexTheCharr/gofurry-cloud-service/common/util"
	"github.com/PhlexTheCharr/gofurry-cloud-service/roof/env"
)

var newInitDB = new(initDB)

type initDB struct{ abstract.Dao }

func GetInitDB() *initDB { return newInitDB }

func init() {
	newInitDB.Init()
}

func (dao *initDB) InitDataBase() {
	var err error

	switch env.GetServerConfig().DataBase.Name {
	case "postgres":
		initPostgreSQL()
	case "mysql":
		initMySQL()
	case "sqlite":
		initSQLite()
	default:
		log.Error("DB type is not ranged from sqlite or postgres or mysql")
		panic("DB type is not ranged from sqlite or postgres or mysql")
	}
	// 自动初始化表
	err = dao.Gm.AutoMigrate(&oum.OlSaying{}) // 自动迁移：表不存在则创建，存在则更新结构
	err = dao.Gm.AutoMigrate(&lm.GfcLog{})

	if err != nil {
		panic("迁移表结构失败: " + err.Error())
	}
}

// 初始化SQLite
func initSQLite() {
	dbPath := env.GetServerConfig().DataBase.Sqlite.DBPath
	if dbPath == "" {
		log.Error("SQLite 配置错误：db_path 为空")
		panic("SQLite db_path is empty")
	}
	if !util.FileExists(dbPath) {
		log.Info("SQLite 数据库文件不存在，即将创建：", dbPath)
	} else {
		log.Info("SQLite 数据库文件已存在：", dbPath)
	}
}

// 初始化 MySQL
func initMySQL() {
	cfg := env.GetServerConfig().DataBase.Mysql
	if cfg.DBName == "" || cfg.DBUsername == "" || cfg.DBHost == "" || cfg.DBPort == "" {
		log.Error("MySQL配置错误: 数据库名、用户名、主机或端口不能为空")
		return
	}

	if err := createMySQLDatabase(cfg); err != nil {
		log.Error("MySQL<UNK>: " + err.Error())
		return
	}
}

// 初始化PostgreSQL数据库
func initPostgreSQL() {
	cfg := env.GetServerConfig().DataBase.Postgres
	if cfg.DBName == "" || cfg.DBUsername == "" || cfg.DBHost == "" || cfg.DBPort == "" {
		log.Error("PostgreSQL配置错误: 数据库名、用户名、主机或端口不能为空")
		return
	}

	if err := createPostgreSQLDatabase(cfg); err != nil {
		log.Error("PostgreSQL<UNK>: " + err.Error())
		return
	}
}

// MySQL 自动创建数据库
func createMySQLDatabase(cfg env.MysqlConfig) error {
	// 连接时不指定数据库名
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/?charset=utf8mb4",
		cfg.DBUsername, cfg.DBPassword, cfg.DBHost, cfg.DBPort)

	db, err := sql.Open("mysql", dsn)
	if err != nil {
		return fmt.Errorf("连接MySQL失败（创建数据库前）: %w", err)
	}
	defer db.Close()

	// 如果不存在就创建数据库
	createSQL := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", cfg.DBName)
	_, err = db.Exec(createSQL)
	if err != nil {
		return fmt.Errorf("创建MySQL数据库失败: %w", err)
	}

	log.Info("MySQL数据库 '%s' 已准备就绪（已存在或新创建）", cfg.DBName)
	return nil
}

// PostgreSQL 自动创建数据库
func createPostgreSQLDatabase(cfg env.PostgresConfig) error {
	// 连接时不指定数据库名
	dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=postgres sslmode=disable",
		cfg.DBHost, cfg.DBPort, cfg.DBUsername, cfg.DBPassword)

	// 使用原生sql包连接
	db, err := sql.Open("pgx", dsn)
	if err != nil {
		return fmt.Errorf("连接PostgreSQL失败（创建数据库前）: %w", err)
	}
	defer db.Close()

	// 如果不存在就创建数据库
	var dbExists bool
	checkSQL := "SELECT EXISTS(SELECT 1 FROM pg_database WHERE datname = $1)"
	err = db.QueryRow(checkSQL, cfg.DBName).Scan(&dbExists)
	if err != nil {
		return fmt.Errorf("检查PostgreSQL数据库是否存在失败: %w", err)
	}

	if !dbExists {
		createSQL := fmt.Sprintf("CREATE DATABASE \"%s\"", cfg.DBName)
		_, err = db.Exec(createSQL)
		if err != nil {
			return fmt.Errorf("创建PostgreSQL数据库失败: %w", err)
		}
		log.Info("PostgreSQL数据库 '%s' 已创建", cfg.DBName)
	} else {
		log.Info("PostgreSQL数据库 '%s' 已存在", cfg.DBName)
	}
	return nil
}
